package models

import (
	"cgs-server/helper"
	"cgs-server/server/cgs/app/models/filter"
	"cgs-server/server/model"
	"errors"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

// 页面类型
const (
	// WorksheetType 表单
	WorksheetType = iota
	// CustomPageType 自定义页面
	CustomPageType
)

// WorksheetInfo 表格信息
type WorksheetInfo struct {

	// Id 表单id
	Id primitive.ObjectID `json:"id" bson:"id"`

	// Name 表格名称
	Name string `json:"name" bson:"name"`

	// Fields 字段
	Fields *Fields `json:"fields,omitempty" bson:"fields,omitempty"`

	// Config 配置信息
	Config interface{} `json:"config,omitempty" bson:"config,omitempty"`

	// AppId 应用Id
	AppId string `json:"appId" bson:"appId"` // 应用 id

	// GroupId 分组id
	GroupId string `json:"groupId" bson:"groupId"`

	// Type 表单类型，0：表单，1：自定义页面
	Type *int `json:"type" bson:"type"`

	// Icon
	Icon string `json:"icon" bson:"icon"`

	// 是否隐藏，隐藏后只有管理员可以看见
	Hidden *bool `json:"hidden" bson:"hidden"`

	// 全部视图的 qrcode
	AllViewQRCode string `json:"allViewQRCode" bson:"allViewQRCode"`

	// ShareState 分享状态
	ShareState *int `json:"shareState" bson:"shareState"`

	model.TenantModel `json:",inline" bson:",inline"`
}

type WorksheetInfoList []*WorksheetInfo

type Fields []*Field

// GetField 根据 name 查询字段信息
func (f *Fields) GetField(name string) *Field {
	for _, field := range *f {
		if field.Name == name {
			return field
		}
	}

	return nil
}

func (f *Fields) GetDataType(name string) filter.DataType {
	for _, field := range *f {
		if field.Name == name {
			return field.DataType
		}
	}

	return filter.NotExitType
}

func (f *Fields) GetOptions(name string) VFormFieldOptions {
	for _, field := range *f {
		if field.Name == name {
			return field.Options
		}
	}

	return nil
}

func (f *Fields) GetDataTypeAndOptions(name string) (filter.DataType, VFormFieldOptions) {
	for _, field := range *f {
		if field.Name == name {
			return field.DataType, field.Options
		}
	}

	return filter.NotExitType, nil
}

func (w *WorksheetInfo) SetId(id primitive.ObjectID) {
	w.Id = id
}

func (w *WorksheetInfo) GetId() string {
	return w.Id.Hex()
}

func (w *WorksheetInfo) ResolveFields(preFields *Fields) error {
	if w.Type == nil || *w.Type != 0 {
		return nil
	}
	if w.Config == nil {
		return nil
	}

	config, ok := w.Config.(string)
	if !ok {
		return errors.New("config requires a string")
	}
	if config == "" {
		return nil
	}
	var vForm VForm
	err := helper.FromJSON([]byte(config), &vForm)
	if err != nil {
		return err
	}
	fields, err := vForm.ResolveFields()
	if err != nil {
		return err
	}
	// 生成或更新子表单的 formId
	for _, field := range fields {
		if field.IsSubForm() {
			// 是子表
			if preFields != nil {
				getField := preFields.GetField(field.Name)
				if getField != nil && getField.SubFormId != "" {
					field.SubFormId = getField.SubFormId
				} else {
					field.SubFormId = primitive.NewObjectID().Hex()
				}
			} else {
				field.SubFormId = primitive.NewObjectID().Hex()
			}
		}
	}
	if preFields != nil {

	}

	w.Fields = &fields
	return nil
}

// Field 表格字段信息
type Field struct {

	// Name 字段名
	Name string `json:"name" bson:"name"`

	// Alia 别名，中文名
	Alia string `json:"alia,omitempty" bson:"alia,omitempty"`

	// DataType 类型
	DataType filter.DataType `json:"dataType" bson:"dataType"`

	// Options 其他属性
	Options VFormFieldOptions `json:"options,omitempty" bson:"options,omitempty"`

	// SubFields 子表字段数据
	SubFields *Fields `json:"subFields,omitempty" bson:"subFields,omitempty"`

	// SubFormId 子表 ID，需要一个 primitive.ObjectID 的 hex 值，以便后续转换为独立的表单
	SubFormId string `json:"subFormId,omitempty" bson:"subFormId,omitempty"`

	// ParentKey 工作流中配置节点输出使用
	ParentKey string `json:"parentKey,omitempty" bson:"parentKey,omitempty"`
}

func (f *Field) IsSubForm() bool {
	return f.DataType == filter.DetailTable
}

// WorksheetView 表单视图
type WorksheetView struct {

	// Id 视图Id
	Id primitive.ObjectID `json:"id" bson:"id"`

	// Name 视图名称
	Name string `json:"name" bson:"name"`

	// ViewType 视图类型
	ViewType *int `json:"viewType" bson:"viewType"`

	// WorksheetId 表单Id
	WorksheetId string `json:"worksheetId" bson:"worksheetId"`
}

type WorksheetViewList []*WorksheetView
